package com.nxzh.de.executor.aspectj;

import com.nxzh.de.executor.common.constant.Constants;
import com.nxzh.de.executor.common.core.redis.RedisCache;
import com.nxzh.de.executor.common.utils.StringUtils;
import com.nxzh.de.executor.config.datasource.DynamicDataSourceContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 拦截dao方法切面，给jar包切换指定的数据源
 */
@Aspect
@Component
@Slf4j
@Order(1)
public class DynamicDataSourceAspect {

    @Autowired
    private RedisCache redisCache;

    @Around("execution(* com.nxzh.de.executor.mapper.*..*(..))")
    public Object around(ProceedingJoinPoint point) throws Throwable {

        Object[] mapperInterfaces = point.getTarget().getClass().getInterfaces();
        String mapperInterfaceName = "";
        if (mapperInterfaces.length > 0) {
            mapperInterfaceName = point.getTarget().getClass().getInterfaces()[0].getName();
        }

        Collection<String> packages = redisCache.keys(Constants.DATA_SOURCE_KEY + "*");
        try {
            final String interfaceName = mapperInterfaceName;
            List<String> stringList = packages.stream().filter(packag -> StringUtils.startsWithAny(Constants.DATA_SOURCE_KEY + interfaceName, packag)).collect(Collectors.toList());
            // 数据源不唯一或不存在时，直接放走
            if (stringList.size() != 1)
                return point.proceed();

            String source_code = redisCache.getCacheObject(stringList.get(0));
            if (StringUtils.isNotEmpty(source_code)) {
                DynamicDataSourceContextHolder.setDataSourceType(source_code);
            }

            return point.proceed();
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            DynamicDataSourceContextHolder.clearDataSourceType();
        }
    }
}
